package com.wsm.common.utils;

import com.alibaba.fastjson.JSONObject;
import com.sun.mail.util.MailSSLSocketFactory;
import com.wsm.common.config.BaseConfig;
import com.wsm.common.config.CloseConfig;
import com.wsm.common.enums.CloseKey;
import com.wsm.common.enums.ConfigKey;
import com.wsm.system.domain.UserDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.security.GeneralSecurityException;
import java.util.Properties;

/**
 * @name: EmailUtils
 * @Author: wangshimin
 * @Date: 2020/2/6  21:13
 * @Description:
 */
@Slf4j
@Component
public class EmailUtils {

    @Autowired
    CloseConfig closeConfig;
    @Autowired
    BaseConfig baseConfig;

    /**
     * 发送用户注册通知邮件
     *
     * @param userDO
     */
    @Async("asyncSendEmailExecutor")
    public void sendRegisterEmail(UserDO userDO) {
        if (!closeConfig.getMap(CloseKey.Email.getValue())) {
            return;
        }
        String title = "欢迎注册springboot个人博客用户";
        String content = getContent(userDO);
        String recipientEmail = userDO.getEmail();
        try {
            sendEmail(recipientEmail, title, content);
            log.info("[用户注册成功通知邮件] {} 用户已成功发送通知邮件", JSONUtils.beanToJson(userDO));
        } catch (GeneralSecurityException | MessagingException e) {
            log.error("[用户注册成功通知邮件] {} 用户发送通知邮件失败", JSONUtils.beanToJson(userDO));
        }
    }

    /**
     * 发送普通邮件
     *
     * @throws MessagingException
     * @throws GeneralSecurityException
     */
    public void sendEmail(String recipientEmail, String title, String content) throws MessagingException, GeneralSecurityException {
        Object map = baseConfig.getMap(ConfigKey.Email.getValue());
        if (null == map) {
            log.error("未配置email信息，无法发送邮件");
            return;
        }
        JSONObject jsonObject = JSONObject.parseObject(map.toString());
        String host = jsonObject.get("host").toString();
        String user = jsonObject.get("user").toString();
        String password = jsonObject.get("password").toString();
        String sendEmail = jsonObject.get("sendEmail").toString();
        Session session = setSession(host, user, password);
        //2、通过session得到transport对象
        Transport ts = session.getTransport();
        //3、使用邮箱的用户名和授权码连上邮件服务器
        ts.connect(host, user, password);
        //4、创建邮件
        //创建邮件对象
        MimeMessage message = new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress(sendEmail));
        //指明邮件的收件人，现在发件人和收件人是一样的，那就是自己给自己发
        message.setRecipient(Message.RecipientType.TO, new InternetAddress(recipientEmail));
        //邮件的标题
        message.setSubject(title);
        //邮件的文本内容
        message.setContent(content, "text/html;charset=UTF-8");
        //5、发送邮件
        ts.sendMessage(message, message.getAllRecipients());
        ts.close();
    }

    private Session setSession(String host, String user, String password) throws GeneralSecurityException, NullPointerException {
        Properties prop = new Properties();
        prop.setProperty("mail.host", host); //// 设置QQ邮件服务器
        prop.setProperty("mail.transport.protocol", "smtp"); // 邮件发送协议
        prop.setProperty("mail.smtp.auth", "true"); // 需要验证用户名密码
        // 关于QQ邮箱，还要设置SSL加密，加上以下代码即可
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        prop.put("mail.smtp.ssl.enable", "true");
        prop.put("mail.smtp.ssl.socketFactory", sf);
        //使用JavaMail发送邮件的5个步骤
        //创建定义整个应用程序所需的环境信息的 Session 对象
        Session session = Session.getDefaultInstance(prop, new Authenticator() {
            @Override
            public PasswordAuthentication getPasswordAuthentication() {
                //发件人邮件用户名、授权码
                return new PasswordAuthentication(user, password);
            }
        });
        //开启Session的debug模式，这样就可以查看到程序发送Email的运行状态
        session.setDebug(false);
        return session;
    }

    /**
     * 发送图片邮件
     *
     * @throws GeneralSecurityException
     * @throws MessagingException
     */
    public void sendPhototEmail(String photoFile, String photoName,
                                String recipientEmail, String title, String content)
            throws GeneralSecurityException, MessagingException {
        Object map = baseConfig.getMap(ConfigKey.Email.getValue());
        if (null == map) {
            log.error("未配置email信息，无法发送邮件");
            return;
        }
        JSONObject jsonObject = JSONObject.parseObject(map.toString());
        String host = jsonObject.get("host").toString();
        String user = jsonObject.get("user").toString();
        String password = jsonObject.get("password").toString();
        String sendEmail = jsonObject.get("sendEmail").toString();
        Session session = setSession(host, user, password);
        //2、通过session得到transport对象
        Transport ts = session.getTransport();
        //3、使用邮箱的用户名和授权码连上邮件服务器
        ts.connect(host, user, password);
        //4、创建邮件
        //创建邮件
        MimeMessage message = new MimeMessage(session);
        // 设置邮件的基本信息
        //发件人
        message.setFrom(new InternetAddress(sendEmail));
        //收件人
        message.setRecipient(Message.RecipientType.TO, new InternetAddress(recipientEmail));
        //邮件标题
        message.setSubject(title);
        // 准备邮件数据
        // 准备图片数据
        MimeBodyPart image = new MimeBodyPart();
        DataHandler dh = new DataHandler(new FileDataSource(photoFile));
        image.setDataHandler(dh);
        image.setContentID(photoName);
        // 准备正文数据
        MimeBodyPart text = new MimeBodyPart();
        text.setContent(content, "text/html;charset=UTF-8");
        // 描述数据关系
        MimeMultipart mm = new MimeMultipart();
        mm.addBodyPart(text);
        mm.addBodyPart(image);
        mm.setSubType("related");
        //设置到消息中，保存修改
        message.setContent(mm);
        message.saveChanges();
        //5.发送邮件
        ts.sendMessage(message, message.getAllRecipients());
        ts.close();
    }

    /**
     * 发送邮件图片
     *
     * @param
     * @throws MessagingException
     * @throws GeneralSecurityException
     */
    public void sendFileEmail(String photoFile, String photoName,
                              String recipientEmail, String title, String content,
                              String file, String fileName)
            throws MessagingException, GeneralSecurityException {
        Object map = baseConfig.getMap(ConfigKey.Email.getValue());
        if (null == map) {
            log.error("未配置email信息，无法发送邮件");
            return;
        }
        JSONObject jsonObject = JSONObject.parseObject(map.toString());
        String host = jsonObject.get("host").toString();
        String user = jsonObject.get("user").toString();
        String password = jsonObject.get("password").toString();
        String sendEmail = jsonObject.get("sendEmail").toString();
        Session session = setSession(host, user, password);
        Transport tp = session.getTransport();
        //3.连接服务器,需要抛出异常；
        tp.connect(host, user, password);
        //4.连接上之后我们需要发送邮件；
        //消息的固定信息
        MimeMessage mimeMessage = new MimeMessage(session);
        //邮件发送人
        mimeMessage.setFrom(new InternetAddress(sendEmail));
        //邮件接收人，可以同时发送给很多人，我们这里只发给自己；
        mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(recipientEmail));
        mimeMessage.setSubject(title); //邮件主题
        /*
        编写邮件内容
        1.图片
        2.附件
        3.文本
         */
        //图片
        MimeBodyPart body1 = new MimeBodyPart();
        body1.setDataHandler(new DataHandler(new FileDataSource(photoFile)));
        body1.setContentID(photoName); //图片设置ID
        //文本
        MimeBodyPart body2 = new MimeBodyPart();
        body2.setContent(content, "text/html;charset=utf-8");
        //附件 多个附件设置多个MimeBodyPart就可以
        MimeBodyPart body3 = new MimeBodyPart();
        body3.setDataHandler(new DataHandler(new FileDataSource(file)));
        body3.setFileName(fileName); //附件设置名字

        //拼装邮件正文内容
        MimeMultipart multipart1 = new MimeMultipart();
        multipart1.addBodyPart(body1);
        multipart1.addBodyPart(body2);
        multipart1.setSubType("related"); //1.文本和图片内嵌成功！
        new MimeBodyPart().setContent(multipart1); //将拼装好的正文内容设置为主体
        MimeBodyPart contentText = new MimeBodyPart();
        contentText.setContent(multipart1);
        //拼接附件
        MimeMultipart allFile = new MimeMultipart();
        allFile.addBodyPart(body3); //附件
        allFile.addBodyPart(contentText);//正文
        allFile.setSubType("mixed"); //正文和附件都存在邮件中，所有类型设置为mixed；
        //放到Message消息中
        mimeMessage.setContent(allFile);
        mimeMessage.saveChanges();//保存修改
        //5.发送邮件
        tp.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
        //6.关闭连接
        tp.close();

    }


    //用户注册成功邮件模板
    private static String getContent(UserDO userDO) {
        return "<div style=\"background-color:#ECECEC; padding: 35px;\">\n" +
                "    <table cellpadding=\"0\" align=\"center\"\n" +
                "           style=\"width: 600px; margin: 0px auto; text-align: left; position: relative; border-top-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; font-size: 14px; font-family:微软雅黑, 黑体; line-height: 1.5; box-shadow: rgb(153, 153, 153) 0px 0px 5px; border-collapse: collapse; background-position: initial initial; background-repeat: initial initial;background:#fff;\">\n" +
                "        <tbody>\n" +
                "        <tr>\n" +
                "            <th valign=\"middle\"\n" +
                "                style=\"height: 25px; line-height: 25px; padding: 15px 35px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #42a3d3; background-color: #49bcff; border-top-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px;\">\n" +
                "                <font face=\"微软雅黑\" size=\"5\" style=\"color: rgb(255, 255, 255); \">注册成功! （springBoot个人博客）</font>\n" +
                "            </th>\n" +
                "        </tr>\n" +
                "        <tr>\n" +
                "            <td>\n" +
                "                <div style=\"padding:25px 35px 40px; background-color:#fff;\">\n" +
                "                    <h2 style=\"margin: 5px 0px; \">\n" +
                "                        <font color=\"#333333\" style=\"line-height: 20px; \">\n" +
                "                            <font style=\"line-height: 22px; \" size=\"4\">\n" +
                "                                亲爱的 " + userDO.getName()
                + "</font>\n" +
                "                        </font>\n" +
                "                    </h2>\n" +
                "                    <p>首先感谢您加入本" +
                "网站！下面是您的账号信息<br>\n" +
                "                        您的账号：<b>" + userDO.getUsername() + "</b><br>\n" +
                "                        您的密码：<b>" + userDO.getPassword() + "</b><br>\n" +
                "                        建议您即时登录本网站修改登陆密码<br>\n" +
                "                        网站地址：<b><a href=\"http:\\\\www.wangshimin.top\">www.wangshimin.top</a></b><br>\n" +
                "                    <div style=\"width:700px;margin:0 auto;\">\n" +
                "                        <div style=\"padding:10px 10px 0;border-top:1px solid #ccc;color:#747474;margin-bottom:20px;line-height:1.3em;font-size:12px;\">\n" +
                "                            <p>此为系统邮件，请勿回复<br>\n" +
                "                                请保管好您的邮箱，避免账号被他人盗用\n" +
                "                            </p>\n" +
                "                        </div>\n" +
                "                    </div>\n" +
                "                </div>\n" +
                "            </td>\n" +
                "        </tr>\n" +
                "        </tbody>\n" +
                "    </table>\n" +
                "</div>\n";
    }
}
